package com.ajavaer.framework.generator.reader;

import com.ajavaer.framework.common.tools.ObjectTools;
import com.ajavaer.framework.common.tools.ReflectTools;
import com.ajavaer.framework.common.tools.StringTools;
import com.ajavaer.framework.common.validate.Validation;
import com.ajavaer.framework.config.GeneratorConfig;
import com.ajavaer.framework.core.orm.RunSQL;
import com.ajavaer.framework.generator.model.ClassField;
import com.ajavaer.framework.generator.model.ClassInfo;
import com.ajavaer.framework.office.Excel;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;

@Component
public class InfoReader {
    @Resource
    private GeneratorConfig generatorConfig;
    @Resource
    private RunSQL runSQL;
    @Resource
    private Environment environment;

    public Set<String> parentClassFields() {
        Set<String> result = new HashSet<>();
        String superPoClass = generatorConfig.getSuperPoClass();
        Class<?> clazz = null;
        try {
            clazz = Class.forName(superPoClass);
        } catch (ClassNotFoundException e) {
            throw Validation.error("无法访问类:" + superPoClass);
        }
        List<Field> fields = ReflectTools.getAllFields(clazz);
        for (Field field : fields) {
            result.add(field.getName());
        }
        return result;
    }

    public List<ClassInfo> readExcel(File excelFile) throws IOException {
        Sheet sheet = Excel.openExcel(excelFile, 0);
        //扫描表
        Iterator<Row> rowIterator = sheet.rowIterator();
        ClassInfo classInfo = null;
        List<ClassInfo> entities = new ArrayList<>();
        Set<String> superFields = parentClassFields();
        boolean end = true;
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            //第一次
            if (row.getCell(0) != null && StringTools.isNotBlank(stringCellValue(row.getCell(0)))) {
                if (classInfo != null) {
                    entities.add(classInfo);
                }
                classInfo = new ClassInfo();
                String tableName = row.getCell(1).getStringCellValue().trim();
                classInfo.setTableName(tableName);
                classInfo.setSuperPoClass(generatorConfig.getSuperPoClass());
                classInfo.setClassComment(row.getCell(0).getStringCellValue().trim());
                end = false;
            } else if (!end && (row.getCell(0) == null || StringTools.isBlank(row.getCell(0).getStringCellValue())) && row.getCell(1) != null) {
                if (StringTools.isNotBlank(row.getCell(1).getStringCellValue()) && !row.getCell(1).getStringCellValue().equals("字段")) {
                    String column = stringCellValue(row.getCell(1));
                    if (superFields.contains(column)) {//如果该字段父类中已经存在,则不写入
                        continue;
                    }
                    ClassField classField = new ClassField();
                    classField.setColumnName(column);
                    classField.setDbType(row.getCell(2).getStringCellValue().trim());
                    classField.setNotNull(stringCellValue(row.getCell(3)).equalsIgnoreCase("N"));
                    classField.setJpaNamingType(generatorConfig.getJpaNamingType());
                    if (StringTools.isNotBlank(stringCellValue(row.getCell(4)))) {
                        classField.setFieldComment(stringCellValue(row.getCell(4)));
                        if (StringTools.isNotBlank(stringCellValue(row.getCell(6)))) {
                            classField.setFieldComment(classField.getFieldComment() + "（" + stringCellValue(row.getCell(6)) + "）");
                        }
                    }
                    if (ObjectTools.isNotBlank(row.getCell(5))) {
                        classField.setDefaultValue(StringTools.nvl(stringCellValue(row.getCell(5)), null));
                    }
                    classField.process();
                    classInfo.getClassFields().add(classField);
                } else if (row.getCell(1) == null || StringTools.isBlank(stringCellValue(row.getCell(1)))) {
                    end = true;
                }
            } else {
                end = true;
            }
        }
        if (entities.isEmpty() && classInfo != null) {
            entities.add(classInfo);
        }
        return entities;
    }


    public List<ClassInfo> readMySQL() {
        List<ClassInfo> entities = new ArrayList<>();
        String database = generatorConfig.getDatabase();
        if (StringTools.isBlank(database)) {
            database = environment.getProperty("spring.datasource.druid.url");
            if (StringTools.isBlank(database)) {
                throw Validation.error("请指定数据库");
            }
            String[] urlArr = database.split("\\?")[0].split("/");
            database = urlArr[urlArr.length - 1];
        }

        String tables = generatorConfig.getTables();
        boolean part = StringTools.isNotBlank(tables) && !tables.equalsIgnoreCase("all");
        //部分生成,检查对应表是否存在
        List<Object> query = new ArrayList<>();
        query.add(database);
        StringBuilder partPlaceholder = new StringBuilder("(");
        if (part) {
            String tableSQL = "select TABLE_NAME from information_schema.`TABLES` where TABLE_SCHEMA=? AND TABLE_NAME in ";
            List<String> tableList = StringTools.split(tables, ",", String.class);
            for (int i = 0; i < tableList.size(); i++) {
                query.add(tableList.get(i));
                partPlaceholder.append("?");
                if (i < tableList.size() - 1) {
                    partPlaceholder.append(",");
                }
            }
            partPlaceholder.append(")");
            tableSQL += partPlaceholder.toString();
            List<Map<String, Object>> tableCheck = runSQL.executeMap(tableSQL, query.toArray());
            //查询到的表数量和要生成的表数量不一致
            if (tableList.size() != tableCheck.size()) {
                for (Map<String, Object> row : tableCheck) {
                    String tableName = (String) row.get("TABLE_NAME");
                    if (!tableList.contains(tableName)) {
                        throw Validation.error("表[" + tableName + "]不存在");
                    }
                }
            }
        }
        String columnSQL = "select t.TABLE_COMMENT,c.TABLE_NAME,c.COLUMN_NAME,c.COLUMN_TYPE,c.IS_NULLABLE,c.COLUMN_DEFAULT,c.COLUMN_COMMENT from information_schema.`COLUMNS` c INNER JOIN information_schema.`TABLES` t on t.TABLE_NAME=c.TABLE_NAME where c.TABLE_SCHEMA=?";
        if (part) {
            columnSQL += " AND c.TABLE_NAME in " + partPlaceholder.toString();
        }

        Set<String> superFields = parentClassFields();
        List<Map<String, Object>> columnMaps = runSQL.executeMap(columnSQL, query.toArray());
        String nowTalbe = "";
        ClassInfo classInfo;
        List<ClassField> classFields = new ArrayList<>();
        for (Map<String, Object> columnMap : columnMaps) {
            String tableName = columnMap.get("TABLE_NAME").toString();
            if (!tableName.equals(nowTalbe)) {
                String tableComment = columnMap.get("TABLE_COMMENT").toString();
                nowTalbe = tableName;
                classInfo = new ClassInfo();
                classFields = new ArrayList<>();
                classInfo.setTableName(tableName);
                classInfo.setClassComment(tableComment);
                classInfo.setSuperPoClass(generatorConfig.getSuperPoClass());
                classInfo.setClassFields(classFields);
                entities.add(classInfo);
            }
            String columnName = (String) columnMap.get("COLUMN_NAME");
            if (superFields.contains(columnName)) {//如果该字段父类中已经存在,则不写入
                continue;
            }
            ClassField classField = new ClassField();
            classField.setColumnName(columnName);
            classField.setDbType((String) columnMap.get("COLUMN_TYPE"));
            classField.setNotNull(((String) columnMap.get("IS_NULLABLE")).equalsIgnoreCase("NO"));
            classField.setDefaultValue((String) columnMap.get("COLUMN_DEFAULT"));
            classField.setFieldComment((String) columnMap.get("COLUMN_COMMENT"));
            classField.process();
            classFields.add(classField);
        }
        return entities;
    }

    public List<ClassInfo> readPo(Class<?>... pos) {
        List<ClassInfo> entities = new ArrayList<>();
        for (Class<?> po : pos) {
            ClassInfo classInfo = new ClassInfo();
            classInfo.setClassName(po.getSimpleName());
            classInfo.setSuperPoClass(po.getSuperclass().getName());
            entities.add(classInfo);
        }
        return entities;
    }


    private String stringCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        cell.setCellType(CellType.STRING);
        return cell.getStringCellValue();
    }

}
